//
// Created by tianq on 25-6-14.
//
#include <SFML/Graphics.hpp>

template<class T>
std::string toAlignedString(T in, const int width = 4) {
    std::string str = std::to_string(in);
    if (str.length() < width) {
        str.insert(0, width - str.length(), ' ');
    } else if (str.length() > width) {
        str = str.substr(0, width - 1) + "*";
    }
    return str;
}

class DemoWnd {
    sf::RenderWindow window;
    std::string title = "SFML timed 1";
    sf::Clock clock;
    sf::Time logicTime{}, drawTime{}, totalTime{};
    sf::Vector2i mousePos{};
    sf::Vector2f mousePosF{};
    bool leftDown = false;

    std::vector<sf::CircleShape> balls{};

public:
    DemoWnd()
        : window(sf::VideoMode({800, 600}), title) {
        // clock started here
    }

    void draw() {
        window.clear();
        for (const auto &ball: balls) {
            window.draw(ball);
        }
        window.display();
    };

    void mapEvents(const std::optional<sf::Event> &event) {
        if (event->is<sf::Event::Closed>()) {
            window.close();
        }
        if (event->is<sf::Event::MouseMoved>()) {
            mousePos = event->getIf<sf::Event::MouseMoved>()->position;
            mousePosF = sf::Vector2f(mousePos);
        }
        if (event->is<sf::Event::MouseButtonPressed>()) {
            if (event->getIf<sf::Event::MouseButtonPressed>()->button == sf::Mouse::Button::Left) {
                // handle click here
                myFun();
                leftDown = true;
            }
        }
        if (event->is<sf::Event::MouseButtonReleased>()) {
            if (event->getIf<sf::Event::MouseButtonReleased>()->button == sf::Mouse::Button::Left) {
                leftDown = false;
            }
        }
        if (leftDown) {
            // handle drag here
            myFun2();
        }
    };

    void run() {
        while (window.isOpen()) {
            logicTime = clock.getElapsedTime();
            draw();
            totalTime = clock.getElapsedTime();
            drawTime = totalTime - logicTime;
            clock.reset();
            window.setTitle(
                title +
                "\tLogic: " + toAlignedString(logicTime.asMicroseconds()) +
                "\tDraw: " + toAlignedString(drawTime.asMicroseconds()) +
                "\tTotal: " + toAlignedString(totalTime.asMicroseconds())
            );
            const std::optional<sf::Event> event = window.waitEvent();
            clock.start();
            mapEvents(event);
        }
    }

    void myFun() {
        balls.emplace_back(10);
        balls.back().setPosition({mousePosF.x - 10, mousePosF.y - 10});
    }

    void myFun2() {
        balls.back().setPosition({mousePosF.x - 10, mousePosF.y - 10});
    }
};

int main() {
    DemoWnd wnd;
    wnd.run();
}
